package com.ifnk.portaljava.hlyt.dao.impl;

import com.ifnk.portaljava.hlyt.dao.IDeviceLookupJdbcDao;
import com.ifnk.portaljava.hlyt.service.IDeviceLookupService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import java.io.*;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;

public class DeviceLookupLocalImpl implements IDeviceLookupJdbcDao, ResourceLoaderAware, BeanPostProcessor {
	
	private static Log loger = LogFactory.getLog(DeviceLookupLocalImpl.class);

	private Hashtable<String, String> localTable = new Hashtable<String, String>();

	private String filePath;

	private String recordSpliter = ",";
	
	private ResourceLoader myResourceLoader;

	public String getRecordSpliter() {
		return recordSpliter;
	}

	public void setRecordSpliter(String recordSpliter) {
		this.recordSpliter = recordSpliter;
	}

	public DeviceLookupLocalImpl(String filePath) {
		this.setFilePath(filePath);
	}
	
	public DeviceLookupLocalImpl(){
		
	}

	public List<String> findByName(String name) throws Exception {
		//parseFile();
		if(localTable.size() == 0){
			throw new Exception(" local file is empty!");
		}
		List<String> sources = new ArrayList<String>();
		Set<String> keys = localTable.keySet();
		for(String key : keys){
			String deviceName = localTable.get(key);
			if(deviceName.equals(name)){
				sources.add(key);
			}
		}
		return sources;
	}

	public String findDeviceName(String source) throws Exception {
		//parseFile();
		if(localTable.size() == 0){
			throw new Exception(" local file is empty!");
		}
		
		loger.debug("get device from: " + source);
		loger.debug("get device: " + localTable.get(source));
		
		if(localTable.containsKey(source.trim())){
			return localTable.get(source.trim());
		}
		return null;
	}

	public void save(String source ,String name, Connection conn)
			throws Exception {
		// TODO Auto-generated method stub

	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	public String getFilePath() {
		return filePath;
	}

	private void parseFile() {
		BufferedReader buffReader = null;
		localTable.clear();
		try {
			Resource r = myResourceLoader.getResource(filePath);
			buffReader = new BufferedReader(new InputStreamReader(r.getInputStream(), "UTF-8"));
			String record = null;
			int lineIndex = 1;
			while ((record = buffReader.readLine()) != null) {
				analysisRecord(record, lineIndex++);
			}
			buffReader.close();
			buffReader = null;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (buffReader != null) {
				try {
					buffReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void analysisRecord(final String record, final int lineIndex)
			throws Exception {
		String[] recordArr = record.trim().split(recordSpliter);
		if(record.equals("")){
			return;
		}
		if(record.trim().indexOf("#") == 0){
			return;
		}
		File file = new File(filePath);
		//无法分割
		if (recordArr == null) {
			throw new Exception(new StringBuffer().append("the \"")
					.append(record).append("\" is not split at ").append(
							recordSpliter).append(" line :").append(lineIndex)
					.append(" in file:/// ").append(file.getCanonicalPath()).toString());
		}
		//行格式错误
		if (recordArr.length != 2) {
			throw new Exception(new StringBuffer().append("the \"").append(record)
					.append("\" is not validate ").append(" at line:").append(
							lineIndex).append(" in file:/// ").append(file.getCanonicalPath()).toString());
		} else {
			//行有重复
			if (localTable.containsKey(recordArr[0].trim())) {
				/*
				throw new Exception(new StringBuffer().append("the \"").append(
						record).append("\" is repeat at line:").append(lineIndex)
						.append(" in file:/// ").append(file.getCanonicalPath()).toString());
						*/
				return;
			}
			String[] nets = recordArr[0].trim().split("/");
			if (nets.length == 1) {
				localTable.put(recordArr[0].trim(), recordArr[1].trim());
			} else if (nets.length == 2) {
				String[] ips = nets[0].split("\\.");
				int t = (int) Math.pow(2, (32 - Integer.valueOf(nets[1])));
				for (int i = 0; i < t; i++) {
					String ip = ips[0] + "." + ips[1] + "." + ips[2] + "." + String.valueOf(Integer.valueOf(ips[3]) + i);
					localTable.put(ip, recordArr[1].trim());
				}
			}
		}
	}

	// inject by spring
	@Override
	public void setResourceLoader(ResourceLoader arg0) {
		this.myResourceLoader = arg0;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String name)
			throws BeansException {
		
		if (bean instanceof IDeviceLookupService) {
			loger.debug("before parse file " + filePath);
			parseFile();
			loger.debug("local table size: " + localTable.size());
		}
		return bean;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String name)
			throws BeansException {
		return  bean;
	}

	@Override
	public void init() {
		parseFile();
	}
}
